
/**
 * @author lyj
 *
 */

const xmlToFlinkJSON = (function() {
  this.version = '1.0.0'
  // xml对象转json对象
  this.xmlToJson = function(xml) {
    // Create the return object
    var obj = {}
    if (xml.nodeType === 1) { // element
      // do attributes
      if (xml.attributes.length > 0) {
        obj['@attributes'] = {}
        for (var j = 0; j < xml.attributes.length; j++) {
          var attribute = xml.attributes.item(j)
          obj['@attributes'][attribute.nodeName] = attribute.nodeValue
        }
      }
    } else if (xml.nodeType === 3) { // text
      obj = xml.nodeValue
    }
    // do children
    if (xml.hasChildNodes()) {
      for (var i = 0; i < xml.childNodes.length; i++) {
        var item = xml.childNodes.item(i)
        var nodeName = item.nodeName
        if (typeof (obj[nodeName]) === 'undefined') {
          obj[nodeName] = this.xmlToJson(item)
        } else {
          if (typeof (obj[nodeName].length) === 'undefined') {
            var old = obj[nodeName]
            obj[nodeName] = []
            obj[nodeName].push(old)
          }
          obj[nodeName].push(this.xmlToJson(item))
        }
      }
    }
    return obj
  }

  /**
   * 将xml转换为flink参数格式内的model内容
   * @param xmlNode
   * @returns {*}
   */
  this.xmlToFlinkModels = function(xmlNode) {
    const xmlToJsonObj = this.xmlToJson(xmlNode)
    const queryParmJson = xmlToJsonObj
    // 数据格式
    const flinkModels = {
      'models': {
        'model': {
          'info': {},
          'hop': [],
          'step': []
        }
      }
    }
    // 获取hop信息
    const flinkHops = this.createFlinkHops(queryParmJson['root'])
    flinkModels.models.model.hop = flinkHops
    // 获取step信息
    const flinkSteps = this.createFlinkSteps(queryParmJson['root'])
    flinkModels.models.model.step = flinkSteps

    return flinkModels
  }

  /**
   * 读取xml格式对象，转为为flink请求参数格式,hop内容
   * @param argRoot
   * @returns {*[]}
   */
  this.createFlinkHops = function(argRoot) {
    // 样例
    // "hop": [
    //   {
    //     "from": "表输入",
    //     "to": "去除重复记录",
    //     "enabled": "Y"
    //   },
    //   {
    //     "from": "去除重复记录",
    //     "to": "字符串操作",
    //     "enabled": "Y"
    //   }
    // ],

    const rFlinkHops = []
    // 根据 source、target查找前后关系
    const xmlHop = argRoot.hop
    // 判断是否存在多个
    if (Array.isArray(xmlHop)) {
      // 数组的场合
      for (let i = 0; i < xmlHop.length; i++) {
        const xmlHopMxCell = xmlHop[i]['mxCell']
        const xmlHopMxCellAttr = xmlHopMxCell['@attributes']
        const flinkHopItem = this.createFlinkHopsItem(argRoot, xmlHopMxCellAttr)
        rFlinkHops.push(flinkHopItem)
      }
    } else {
      // 只有一个关系的场合
      const xmlHopMxCell2 = xmlHop['mxCell']
      const xmlHopMxCellAttr2 = xmlHopMxCell2['@attributes']
      const flinkHopItem2 = this.createFlinkHopsItem(argRoot, xmlHopMxCellAttr2)
      rFlinkHops.push(flinkHopItem2)
    }

    return rFlinkHops
    // createHops end /////////////////
  }

  /**
   * 读取xml格式对象，转为为flink请求参数格式，step内容
   * @param argRoot
   * @returns {*[]}
   */
  this.createFlinkSteps = function(argRoot) {
    // 样例
    // {
    //   "name": "表输入",
    //   "type": "tableInput",
    //   "connection": {
    //   "id": "",
    //     "name": ""
    // },
    //   "tableName": "",
    //   "iscdc": true,
    //   "primaryKey": "",
    //   "fields": [
    //   {
    //     "stream_name": "id"
    //   },
    //   {
    //     "stream_name": "name"
    //   },
    //   {
    //     "stream_name": "age"
    //   }
    // ]
    // }
    const flinkSteps = []
    // 获取xml内的step内容
    const xmlStepList = argRoot['step']
    for (let i = 0; i < xmlStepList.length; i++) {
      const xmlStepItem = xmlStepList[i]
      const flinkStepItem = this.createFlinkStepItem(xmlStepItem)
      flinkSteps.push(flinkStepItem)
    }

    return flinkSteps
    // createFlinkSteps end /////////////////////
  }

  this.createFlinkStepItem = function(xmlStepItem) {
    // 获取xml内step下的属性信息
    const xmlStepItemAttr = xmlStepItem['@attributes']
    const xmlStepItemData = xmlStepItem['data']
    const xmlStepItemDataAttr = xmlStepItemData['@attributes']
    // 自定义form数据
    const xmlStepItemDataAttrVal = xmlStepItemDataAttr['value']
    const xmlForm = JSON.parse(xmlStepItemDataAttrVal)

    // 获取step的mxGeometry 图形信息
    const xmlStepItemMxCell = xmlStepItem['mxCell']
    const xmlStepItemMxCellMxGeometry = xmlStepItemMxCell['mxGeometry']
    const xmlStepItemMxCellMxGeometryAttrVal = xmlStepItemMxCellMxGeometry['@attributes']
    // 2023年12月25日 修改xy坐标，由保存传入参数获取
    const lGeometryX = xmlStepItemMxCellMxGeometryAttrVal.x
    const lGeometryY = xmlStepItemMxCellMxGeometryAttrVal.y
    // 创建类型
    let flinkStepType = ''
    switch (xmlStepItemAttr.type) {
      case 'TableInput':
        flinkStepType = 'tableInput'
        break
      case 'TableOutput':
        flinkStepType = 'tableOutput'
        break
      default:
        flinkStepType = xmlStepItemAttr.type
        break
    }

    const flinkStepItem = {
      'name': xmlForm.name
      // "type": flinkStepType,
      // "iscdc": true,
      // "primaryKey": ""
    }
    // 2023年12月25日 修改xy坐标，由保存传入参数获取
    flinkStepItem['x'] = lGeometryX
    flinkStepItem['y'] = lGeometryY

    if (xmlForm.connection && xmlForm.type !== 'kafkaInput' && xmlForm.type !== 'kafkaOutput') {
      if (xmlForm.connection.type) {
        flinkStepItem['connection'] = {
          'id': xmlForm.connection.id,
          'name': xmlForm.connection.name,
          'url': xmlForm.connection.url,
          'type': xmlForm.connection.type,
          'username': xmlForm.connection.username,
          'password': xmlForm.connection.password
        }
      } else {
        flinkStepItem['connection'] = {
          'id': xmlForm.connection.id,
          'name': xmlForm.connection.name
        }
      }
    }

    if (xmlForm.table) {
      flinkStepItem['tableName'] = xmlForm.table.name
    }
    if (xmlForm.fields) {
      flinkStepItem['fields'] = xmlForm.fields
    }
    if (xmlForm.keys) {
      flinkStepItem['keys'] = xmlForm.keys
    }
    if (xmlForm.iscdc || xmlForm.type === 'tableInput') {
      flinkStepItem['iscdc'] = xmlForm.iscdc
    }
    if (xmlForm.type) {
      flinkStepItem['type'] = xmlForm.type
    }
    if (xmlForm.primaryKey || xmlForm.type === 'tableInput' || xmlForm.type === 'tableOutput') {
      flinkStepItem['primaryKey'] = xmlForm.primaryKey
    }
    if (xmlForm.field_to_use) {
      flinkStepItem['field_to_use'] = xmlForm.field_to_use
    }
    if (xmlForm.target_field) {
      flinkStepItem['target_field'] = xmlForm.target_field
    }
    if (xmlForm.non_match_default) {
      flinkStepItem['non_match_default'] = xmlForm.non_match_default
    }
    if (xmlForm.split_field) {
      flinkStepItem['split_field'] = xmlForm.split_field
    }
    if (xmlForm.delimiter) {
      flinkStepItem['delimiter'] = xmlForm.delimiter
    }
    if (xmlForm.join_type) {
      flinkStepItem['join_type'] = xmlForm.join_type
    }
    if (xmlForm.step1) {
      flinkStepItem['step1'] = xmlForm.step1
    }
    if (xmlForm.step2) {
      flinkStepItem['step2'] = xmlForm.step2
    }
    if (xmlForm.keys_1) {
      flinkStepItem['keys_1'] = xmlForm.keys_1
    }
    if (xmlForm.keys_2) {
      flinkStepItem['keys_2'] = xmlForm.keys_2
    }
    if (xmlForm.executeType) {
      flinkStepItem['executeType'] = xmlForm.executeType
    }
    if (xmlForm.sql && xmlForm.type === 'ExecSQL') {
      flinkStepItem['sql'] = xmlForm.sql
    }
    if (xmlForm.url) {
      flinkStepItem['url'] = ''
    }
    if (xmlForm.inputType) {
      flinkStepItem['inputType'] = xmlForm.inputType
    }
    if (xmlForm.outputType) {
      flinkStepItem['outputType'] = xmlForm.outputType
    }
    // if (xmlForm.calc_type) {
    //   flinkStepItem['calc_type'] = xmlForm.calc_type
    // }
    return flinkStepItem
  }

  /**
   * 创建flink格式的hop数据
   * @param argRoot
   * @param xmlHopMxCellAttr
   * @returns {{from: string, to: string, enabled: string}}
   */
  this.createFlinkHopsItem = function(argRoot, xmlHopMxCellAttr) {
    // 样例
    // "hop": [
    //   {
    //     "from": "表输入",
    //     "to": "去除重复记录",
    //     "enabled": "Y"
    //   },
    //   {
    //     "from": "去除重复记录",
    //     "to": "字符串操作",
    //     "enabled": "Y"
    //   }
    // ],
    const lFlinkHopItem = {
      'from': '',
      'to': '',
      'enabled': 'Y'
    }
    // 获取xml内的关系
    const xmlSource = xmlHopMxCellAttr['source']
    const xmlTarget = xmlHopMxCellAttr['target']

    let xmlFormID = ''
    let xmlToID = ''
    // 查询获取关系对应的节点ID
    const xmlMxCellList = argRoot['mxCell']
    for (let i = 0; i < xmlMxCellList.length; i++) {
      const xmlRootMxCells = xmlMxCellList[i]
      const xmlRootMxCellAttr = xmlRootMxCells['@attributes']
      if (xmlRootMxCellAttr['id'] === xmlSource) {
        xmlFormID = xmlRootMxCellAttr['parent']
      }
      if (xmlRootMxCellAttr['id'] === xmlTarget) {
        xmlToID = xmlRootMxCellAttr['parent']
      }
    }
    // 获取xml内的step
    const xmlFormStepItem = this.getXmlStepByID(argRoot, xmlFormID)
    const xmlToStepItem = this.getXmlStepByID(argRoot, xmlToID)

    lFlinkHopItem.from = xmlFormStepItem['@attributes']['name']
    lFlinkHopItem.to = xmlToStepItem['@attributes']['name']

    return lFlinkHopItem
    // createFlinkHopsItem end ////////////////
  }

  /**
   * 根据step的ID，获取xml中的step信息
   * @param argRoot
   * @param argStepID
   */
  this.getXmlStepByID = function(argRoot, argStepID) {
    const xmlStepList = argRoot['step']
    for (let i = 0; i < xmlStepList.length; i++) {
      const xmlStepItem = xmlStepList[i]
      if (xmlStepItem['@attributes']['id'] === argStepID) {
        return xmlStepItem
      }
    }
    return null
  }

  /**
   * 创建flink保存数据参数
   * @param argXmlNode
   * @returns {{jobName: string, models: {}, taskType: string, taskScheduleType: string, flinkJobParam: {fragment: boolean, alertGroupId: null, dialect: string, clusterConfigurationId: null, parallelism: number, savePointPath: null, batchModel: boolean, clusterId: number, type: string, statementSet: boolean, checkPoint: number, savePointStrategy: null}, id: string, taskId: string}}
   */
  this.createFlinkSavaParameter = function(argXmlNode) {
    const xmlToJsonObj = this.xmlToJson(argXmlNode)
    const queryParmJson = xmlToJsonObj
    // 数据格式
    const flinkModels = {
      'models': {
        'model': {
          'info': {},
          'hop': [],
          'step': []
        }
      }
    }
    // 获取hop信息
    const flinkHops = this.createFlinkHops(queryParmJson['root'])
    flinkModels.models.model.hop = flinkHops
    // 获取step信息
    const flinkSteps = this.createFlinkSteps(queryParmJson['root'])
    flinkModels.models.model.step = flinkSteps

    const lFlinkSavaPram = {
      'jobName': '',
      'taskType': 'FlinkComponent',
      'taskScheduleType': 'realtime',
      'id': '',
      'taskId': '',
      'flinkJobParam': {
        'type': 'standalone',
        'clusterId': 3,
        'clusterConfigurationId': null,
        'parallelism': 1,
        'checkPoint': 0,
        'statementSet': false,
        'fragment': false,
        'batchModel': false,
        'alertGroupId': null,
        'dialect': 'FlinkComponent',
        'savePointPath': null,
        'savePointStrategy': null
      },
      'models': {}
    }

    lFlinkSavaPram.models = flinkModels.models
    // 获取任务信息
    const lXmlTaskInfor = this.createFlinkTaskInfo(queryParmJson['root'])
    lFlinkSavaPram.jobName = lXmlTaskInfor.jobName
    lFlinkSavaPram.taskType = lXmlTaskInfor.taskType
    lFlinkSavaPram.taskScheduleType = lXmlTaskInfor.taskScheduleType

    return lFlinkSavaPram
  }

  this.createFlinkTaskInfo = function(argXmlRoot) {
    const xmlInfo = argXmlRoot['info']
    const lFlinkTask = {
      'jobName': '', // 任务名
      'taskType': 'FlinkComponent', // 任务类型
      'taskScheduleType': 'realtime', // 调度类型
      'id': '', // 主键id
      'taskId': '' // 任务id
    }
    const xmlInfoAttr = xmlInfo['@attributes']
    lFlinkTask.jobName = xmlInfoAttr['name']
    return lFlinkTask
  }

  return this
}.call({}))

export default xmlToFlinkJSON
// if (typeof module !== 'undefined' && module !== null && module.exports) module.exports = xmlToFlinkJSON
// else if (typeof define === 'function' && define.amd) define(function() { return xmlToFlinkJSON })
